gboolean soft_reboot_target;
char **overlay_initrds;
char *overlay_initrds_id;
+
+ // Private cache of expected backing device/inode
+ gboolean devino_initialized;
+ dev_t device;
+ ino_t inode;
};
void _ostree_deployment_set_bootcsum (OstreeDeployment *self, const char *bootcsum);
OstreeDeployment *ret = ostree_deployment_new (
self->index, self->osname, self->csum, self->deployserial, self->bootcsum, self->bootserial);
+ ret->devino_initialized = TRUE;
+ ret->device = self->device;
+ ret->inode = self->inode;
+
new_bootconfig = ostree_bootconfig_parser_clone (self->bootconfig);
ostree_deployment_set_bootconfig (ret, new_bootconfig);
* @inout_deployments: All deployments in this subdir will be appended to this array
*/
gboolean
-_ostree_sysroot_list_deployment_dirs_for_os (int deploydir_dfd, const char *osname,
- GPtrArray *inout_deployments,
+_ostree_sysroot_list_deployment_dirs_for_os (OstreeSysroot *self, int deploydir_dfd,
+ const char *osname, GPtrArray *inout_deployments,
GCancellable *cancellable, GError **error)
{
g_auto (GLnxDirFdIterator) dfd_iter = {
if (!_ostree_sysroot_parse_deploy_path_name (dent->d_name, &csum, &deployserial, error))
return FALSE;
- g_ptr_array_add (inout_deployments,
- ostree_deployment_new (-1, osname, csum, deployserial, NULL, -1));
+ OstreeDeployment *deploy = _ostree_sysroot_new_deployment_object (
+ self, osname, csum, deployserial, NULL, -1, error);
+ if (!deploy)
+ return FALSE;
+ g_ptr_array_add (inout_deployments, deploy);
}
return TRUE;
if (dent->d_type != DT_DIR)
continue;
- if (!_ostree_sysroot_list_deployment_dirs_for_os (dfd_iter.fd, dent->d_name, ret_deployments,
- cancellable, error))
+ if (!_ostree_sysroot_list_deployment_dirs_for_os (self, dfd_iter.fd, dent->d_name,
+ ret_deployments, cancellable, error))
return FALSE;
}
if (!glnx_opendirat (self->sysroot_fd, "ostree/deploy", TRUE, &deploy_dfd, error))
return FALSE;
- if (!_ostree_sysroot_list_deployment_dirs_for_os (deploy_dfd, osname, tmp_current_deployments,
- cancellable, error))
+ if (!_ostree_sysroot_list_deployment_dirs_for_os (self, deploy_dfd, osname,
+ tmp_current_deployments, cancellable, error))
return FALSE;
for (guint i = 0; i < tmp_current_deployments->len; i++)
&checkout_elapsed, &composefs_elapsed, cancellable, error))
return FALSE;
+ struct stat stbuf;
+ if (fstat (deployment_dfd, &stbuf) < 0)
+ return glnx_throw_errno_prefix (error, "fstat(deployment fd)");
+ new_deployment->devino_initialized = TRUE;
+ new_deployment->device = stbuf.st_dev;
+ new_deployment->inode = stbuf.st_ino;
+
g_autoptr (OstreeKernelLayout) kernel_layout = NULL;
if (!get_kernel_from_tree (self, deployment_dfd, &kernel_layout, cancellable, error))
return FALSE;
* higher level code.
*/
OstreeDeployment *
-_ostree_sysroot_deserialize_deployment_from_variant (GVariant *v, GError **error)
+_ostree_sysroot_deserialize_deployment_from_variant (OstreeSysroot *self, GVariant *v,
+ GError **error)
{
g_autoptr (GVariantDict) dict = g_variant_dict_new (v);
const char *name = NULL;
gint deployserial;
if (!_ostree_sysroot_parse_deploy_path_name (name, &checksum, &deployserial, error))
return NULL;
- return ostree_deployment_new (-1, osname, checksum, deployserial, bootcsum, -1);
+ return _ostree_sysroot_new_deployment_object (self, osname, checksum, deployserial, bootcsum, -1,
+ error);
}
/**
&merge_deployment_v))
{
g_autoptr (OstreeDeployment) merge_deployment_stub
- = _ostree_sysroot_deserialize_deployment_from_variant (merge_deployment_v, error);
+ = _ostree_sysroot_deserialize_deployment_from_variant (self, merge_deployment_v, error);
if (!merge_deployment_stub)
return FALSE;
for (guint i = 0; i < self->deployments->len; i++)
gboolean _ostree_sysroot_ensure_writable (OstreeSysroot *self, GError **error);
+// Should be preferred over ostree_deployment_new
+OstreeDeployment *_ostree_sysroot_new_deployment_object (OstreeSysroot *self, const char *osname,
+ const char *csum, int deployserial,
+ const char *bootcsum, int bootserial,
+ GError **error);
+
void _ostree_sysroot_emit_journal_msg (OstreeSysroot *self, const char *msg);
gboolean _ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self, int bootversion,
gboolean _ostree_sysroot_parse_deploy_path_name (const char *name, char **out_csum, int *out_serial,
GError **error);
-gboolean _ostree_sysroot_list_deployment_dirs_for_os (int deploydir_dfd, const char *osname,
+gboolean _ostree_sysroot_list_deployment_dirs_for_os (OstreeSysroot *self, int deploydir_dfd,
+ const char *osname,
GPtrArray *inout_deployments,
GCancellable *cancellable, GError **error);
gboolean _ostree_prepare_soft_reboot (GError **error);
-OstreeDeployment *_ostree_sysroot_deserialize_deployment_from_variant (GVariant *v, GError **error);
+OstreeDeployment *_ostree_sysroot_deserialize_deployment_from_variant (OstreeSysroot *self,
+ GVariant *v, GError **error);
char *_ostree_sysroot_get_deployment_backing_relpath (OstreeDeployment *deployment);
ostree_deployment_get_deployserial (deployment), key);
}
+// Should be preferred over ostree_deployment_new as this also initializes cached
+// state for device/inode.
+OstreeDeployment *
+_ostree_sysroot_new_deployment_object (OstreeSysroot *self, const char *osname, const char *csum,
+ int deployserial, const char *bootcsum, int bootserial,
+ GError **error)
+{
+ if (!ensure_sysroot_fd (self, error))
+ return FALSE;
+
+ // This deployment isn't associated with an index.
+ g_autoptr (OstreeDeployment) ret
+ = ostree_deployment_new (-1, osname, csum, deployserial, bootcsum, bootserial);
+
+ g_autofree char *relpath = ostree_sysroot_get_deployment_dirpath (self, ret);
+ struct stat stbuf;
+ if (!glnx_fstatat (self->sysroot_fd, relpath, &stbuf, AT_SYMLINK_NOFOLLOW, error))
+ return NULL;
+ ret->devino_initialized = TRUE;
+ ret->device = stbuf.st_dev;
+ ret->inode = stbuf.st_ino;
+
+ return g_steal_pointer (&ret);
+}
+
static gboolean
parse_deployment (OstreeSysroot *self, const char *boot_link, OstreeDeployment **out_deployment,
GCancellable *cancellable, GError **error)
is_booted_deployment
= stbuf.st_dev == expected_root_dev && stbuf.st_ino == expected_root_inode;
}
- gboolean is_soft_reboot_target
- = self->have_nextroot
- && (stbuf.st_dev == self->nextroot_device && stbuf.st_ino == self->nextroot_inode);
g_autoptr (OstreeDeployment) ret_deployment
= ostree_deployment_new (-1, osname, treecsum, deployserial, bootcsum, treebootserial);
}
/* TODO: warn on unknown unlock types? */
}
- ret_deployment->soft_reboot_target = is_soft_reboot_target;
+
+ ret_deployment->devino_initialized = TRUE;
+ ret_deployment->device = stbuf.st_dev;
+ ret_deployment->inode = stbuf.st_ino;
g_debug ("Deployment %s.%d unlocked=%d", treecsum, deployserial, ret_deployment->unlocked);
if (target)
{
g_autoptr (OstreeDeployment) staged
- = _ostree_sysroot_deserialize_deployment_from_variant (target, error);
+ = _ostree_sysroot_deserialize_deployment_from_variant (self, target, error);
if (!staged)
return FALSE;
if (self->staged_deployment)
g_ptr_array_insert (deployments, 0, g_object_ref (self->staged_deployment));
- /* And then set their index variables */
+ /* Synchronize internal state now that we've loaded all deployments */
for (guint i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
ostree_deployment_set_index (deployment, i);
+
+ g_assert (deployment->devino_initialized);
+ if (self->have_nextroot && deployment->device == self->nextroot_device
+ && deployment->inode == self->nextroot_inode)
+ {
+ deployment->soft_reboot_target = TRUE;
+ }
}
/* Determine whether we're "physical" or not, the first time we load deployments */